package com.zjs.jsp.fdservice.implement;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zjs.jsp.domain.jsp.AddOrder;
import com.zjs.jsp.domain.jsp.Jsp_Order;
import com.zjs.jsp.domain.jsp.Jsp_Task;
import com.zjs.jsp.fdservice.Help.OnlyDataHelp;
import com.zjs.jsp.fdservice.Interface.AdditionalDataJspTaskInterface;
import com.zjs.jsp.fdservice.service.SendJspTask;
import com.zjs.jsp.fdservice.service.mongodb.ExceptionOrderExpand;
import com.zjs.jsp.fdservice.service.mongodb.JspTaskRepository;
import org.bson.types.ObjectId;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 追加订单处理类
 *
 * @author 李文
 * @create 2017-09-01 16:18
 **/
public class AdditionalDataJspTask implements AdditionalDataJspTaskInterface
{

    private static final OnlyDataHelp ONLY_DATA_HELP = new OnlyDataHelp();
    private static final ObjectMapper JSON = new ObjectMapper();

    /**
     * 分布式 redis 锁
     */
    @Autowired
    private RedissonClient redissonClient;


    /**
     * 路径规矩 接口类
     */
    @Autowired
    private PathPlanning pathPlanning;
    @Autowired
    private JspTaskRepository jspTaskRepository;

    @Autowired
    private SendJspTask sendJspTask;

    @Autowired
    private ExceptionOrderExpand exoExpand;


    /**
     * 获取 需要追加订单的任务包 数据源
     *
     * @param yjxfJspTask 已经下发 并且 未派送的 任务包
     * @return 需要追加订单的任务包 数据源
     */
    @Override
    public LinkedHashMap<String, List<Jsp_Task>> getJspTaskMap(List<Jsp_Task> yjxfJspTask) {
        LinkedHashMap<String, List<Jsp_Task>> mapJspTask = new LinkedHashMap<>();
        //  10 自动分配
        List<Jsp_Task> zdfpJspTask = new ArrayList<>();
        //  30  强制分配
        List<Jsp_Task> qzfpJspTask = new ArrayList<>();
        //  20 抢单
        List<Jsp_Task> qdpJspTask = new ArrayList<>();

        for (Jsp_Task jspTask : yjxfJspTask) {
            //  从已下发过任务包的数据 筛选任务包状态
            if (StringUtils.isEmpty(jspTask.getRwlx())) {
                qdpJspTask.add(jspTask);
                continue;
            }
            switch (jspTask.getRwlx()) {
                case 10:
                    zdfpJspTask.add(jspTask);
                    break;
                case 20:
                    qdpJspTask.add(jspTask);
                    break;
                case 30:
                    qzfpJspTask.add(jspTask);
                    break;
                default:
                    qdpJspTask.add(jspTask);
            }
        }
        mapJspTask.put("zdfpJspTask", zdfpJspTask);
        mapJspTask.put("qzfpJspTask", qzfpJspTask);
        mapJspTask.put("qdpJspTask", qdpJspTask);
        return mapJspTask;
    }

    /**
     * 追加订单逻辑
     *
     * @param jspOrder    当前订单数据
     * @param pk          厅点PK
     * @param js          任务包停留时间
     * @param mi          和包范围  单位 米
     * @param zdfpJspTask 当前状态数据
     * @return 是否追加订单成功  false  运行创建新任务包逻辑
     */
    @Override
    public boolean additionalOrder(Jsp_Order jspOrder, String pk, Integer js, Integer mi, List<Jsp_Task> zdfpJspTask, String strBody) {
        Map<Integer, String> distance = new TreeMap<>();
        //  订单追单
        for (Jsp_Task jspTask : zdfpJspTask) {
            List<Jsp_Order> od = jspTask.getOd();
            if (jspTask.getSum() >= jspTask.getZd() || od == null || od.size() == 0) {
                continue;
            }

            // 获取任务包中第一个订单
            Jsp_Order jspOrder1 = od.get(0);
            //  经纬度距离计算
            BigDecimal decimal = pathPlanning.getShortestDistance(jspOrder, jspOrder1);
            // 判断距离是否符合条件
            if (decimal.intValue() <= mi) {
                distance.put(decimal.intValue(), jspTask.getId());
            }
        }
        // 是否晒单成功
        if (distance.size() == 0) {
            return false;
        }

        // 获取当前订单 与任务包第一单距离最近的 任务包
        String id = "";
        for (String s1 : distance.values()) {
            id = s1;
            break;
        }
        // 分布式 厅点级别锁
        Jsp_Task task;
        RLock lock = redissonClient.getLock(pk);
        try {

            // 上锁
            boolean res = lock.tryLock(20, 10, TimeUnit.SECONDS);
            if (!res) {
                return false;
            }

            task = jspTaskRepository.findOne(new ObjectId(id));
            if (task != null && task.getSum() < task.getZd() && task.getCzzt() != 40) {
                task.setSum(task.getSum() + 1);
                task.setUd(new Date());
                List<Jsp_Order> od = task.getOd();
                od.add(jspOrder);
                task.setOd(od);
                task.setWy(ONLY_DATA_HELP.getWyString(od));
                task.setJs(js);
                AddOrder order = task.toAddOrder(jspOrder);
                // 判断是否是 已经下发 过的任务包   已经下发过的 下发追单信息
                if (task.getXfzt() == 1) {
                    if (!sendJspTask.sendMqData(strBody, jspOrder, order, null)) {
                        throw new Exception("追加订单 下发数据到MQ 是失败");
                    }
                }
                jspTaskRepository.save(task);
            } else {
                return false;
            }
        } catch (Exception e) {
            exoExpand.saveEx(jspOrder, e, " 追加订单异常  运行创建新任务逻辑  数据是 ： " + strBody, 9, "追加订单异常  运行创建新任务逻辑 " + e.getMessage());
        } finally {
            lock.unlock();
        }
        return true;
    }
}
